﻿using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using MJB.UI.ContentEditor.Windows;

namespace MJB.UI.ContentEditor.Commands
{
    /// <summary>
    /// This class defines commands that are hosted in the main window object.
    /// </summary>
    public class MainWindowCommands
    {
        #region Commands

        /// <summary>
        /// This command is fired whenever the user wants to edit the settings of the application.
        /// </summary>
        public static readonly RoutedUICommand SettingsCommand = new RoutedUICommand("Settings",
            "Settings",
            typeof(MainWindowCommands),
            new InputGestureCollection(new KeyGesture[] { new KeyGesture(Key.S, ModifierKeys.Control | ModifierKeys.Shift) }));

        /// <summary>
        /// This command is fired whenever the user wants to save the document that is currently open.
        /// </summary>
        public static readonly RoutedUICommand SaveCommand = new RoutedUICommand("Save Current Document",
            "Save",
            typeof(MainWindowCommands),
            new InputGestureCollection(new KeyGesture[] { new KeyGesture(Key.S, ModifierKeys.Control) }));

        /// <summary>
        /// This command is fired when the application exits.
        /// </summary>
        public static readonly RoutedUICommand ExitCommand = new RoutedUICommand("Exit",
            "Exit",
            typeof(MainWindowCommands),
            new InputGestureCollection(new KeyGesture[] { new KeyGesture(Key.X, ModifierKeys.Control) }));

        #endregion
        #region Constructor

        /// <summary>
        /// The static constructor adds default event handlers.
        /// </summary>
        static MainWindowCommands()
        {

            CommandManager.RegisterClassCommandBinding(typeof(MainWindow),
                new CommandBinding(MainWindowCommands.SettingsCommand,
                    new ExecutedRoutedEventHandler(MainWindowCommands.OnSettingsCommand)));

            CommandManager.RegisterClassCommandBinding(typeof(MainWindow),
                new CommandBinding(MainWindowCommands.SaveCommand,
                    new ExecutedRoutedEventHandler(MainWindowCommands.OnSaveCommand)));

            CommandManager.RegisterClassCommandBinding(typeof(MainWindow),
                new CommandBinding(MainWindowCommands.ExitCommand,
                    new ExecutedRoutedEventHandler(MainWindowCommands.OnExitCommand)));
        }

        #endregion
        #region Event Handlers

        /// <summary>
        /// Called when the settings command is invoked.
        /// </summary>
        /// <param name="sender">The object generating the event.</param>
        /// <param name="args">The arguments of the command.</param>
        public static void OnSettingsCommand(object sender, ExecutedRoutedEventArgs args)
        {
            SettingsWindow settingsWindow = new SettingsWindow();
            settingsWindow.Owner = Application.Current.MainWindow;
            settingsWindow.ShowDialog();
        }
        
        /// <summary>
        /// Called when the save button is clicked.  Verifies that the file 
        /// is valid XML.  Otherwise we'll have a number of problems trying to 
        /// fix it later!
        /// </summary>
        /// <param name="sender">The object generating the event.</param>
        /// <param name="args">The arguments of the command.</param>
        public static void OnSaveCommand(object sender, ExecutedRoutedEventArgs args)
        {
            MainWindow mainWindow = Application.Current.MainWindow as MainWindow;
            if(mainWindow.DisplayedReader == null)
                return;

            Cursor originalCursor = mainWindow.Cursor;
            mainWindow.Cursor = Cursors.Wait;

            try
            {
                // Make sure that the document reader will serialize and deserialize
                // before we send it across the wire!
                XmlWriter xmlWriter = null;
                XmlReader xmlReader = null;

                try
                {
                    // First try serializing the data to a string:
                    StringBuilder writeBuilder = new StringBuilder();
                    xmlWriter = new XmlTextWriter(new StringWriter(writeBuilder));
                    mainWindow.DisplayedReader.WriteXml(xmlWriter);

                    // Now try and read the xml that it wrote:
                    xmlReader = new XmlTextReader(new StringReader(writeBuilder.ToString()));

                    // Read the contents that we just wrote.  
                    // This ensures that whatever we write to the server,
                    // we will be able to read it back!
                    while(xmlReader.Read())
                    {
                    }

                }
                catch(Exception e)
                {
                    e.DisplayError(new StringBuilder("The file could not be saved because it is invalid.  Invalid").Append(Environment.NewLine)
                                             .Append("files cannot be saved to the server because they cannot be").Append(Environment.NewLine)
                                             .Append("parsed properly when they are retrieved at a later date.").Append(Environment.NewLine));
                    throw;

                }
                finally
                {
                    if(xmlWriter != null)
                    {
                        if(xmlWriter.WriteState != WriteState.Closed)
                            xmlWriter.Close();
                    }

                    if(xmlReader != null)
                    {
                        if(xmlReader.ReadState != ReadState.Closed)
                            xmlReader.Close();
                    }

                }

                // Now, once we've validated the data, save the file:
                XmlManagementService managementService = new XmlManagementService();
                managementService.UpdateFile(mainWindow.DisplayedReader.FilePath, mainWindow.DisplayedReader);

            }
            catch(XmlException)
            {
                // Ignored. This was handled above.
            }
            catch(Exception e)
            {
                e.DisplayError(new StringBuilder("There was an error saving the file '")
                                         .Append(mainWindow.DisplayedReader.FilePath)
                                         .Append("'.")
                                         .Append(Environment.NewLine));
            }
            finally
            {
                mainWindow.Cursor = originalCursor;
            }

        }

        /// <summary>
        /// This event handler is fired when the exit command is executed on the main window.
        /// </summary>
        /// <param name="sender">The object generating the event.</param>
        /// <param name="args">The arguments of the command.</param>
        public static void OnExitCommand(object sender, ExecutedRoutedEventArgs args)
        {
            if("Are you sure you want to quit?".DisplayQuestionDialog())
            {
                Application.Current.MainWindow.Close();
            }

        }

        #endregion

    }

}
